package hcs.interfaces;

import hcs.model.Environment;
import hcs.model.Room;
import hcs.model.Room.WindowState;

public abstract class RoomManagementStrategy {

	protected Room room;
	
	/**
	 * Instantiate a new strategy for the requested room
	 * @param room the room to control.
	 */
	public RoomManagementStrategy(Room room) {
		this.room = room;
	}
	
	private RoomManagementStrategy(){}
	
	/**
	 * Applies the heating strategy in order to get the correct temperature for a room.  
	 * @param windowManual tells if the window is manually handled.
	 */
	public void applyStrategy(boolean windowManual) {
		Environment env = room.getHouseController().getEnvironment();
		double tempToFollow = getTemperatureToFollow();
		
		WindowState desiredWS; // desired window state (the next state of the window)
		
		/* Temperature following */
		
		if (room.getTemperature() < tempToFollow-1) {
			desiredWS = roomIsTooCool();
		} else if (room.getTemperature() >= tempToFollow-1 && room.getTemperature() <= tempToFollow+1) {
			desiredWS = roomIsOK();
		} else {
			desiredWS = roomIsTooWarm();
		}
		
		/* Real window actuation */
		
		// if desired window state is open, but it's raining, our desired window state becomes tilted
		if (env.isRaining() && desiredWS.equals(WindowState.OPEN)) {
			desiredWS = WindowState.TILTED;
		}
		
		// only change the window position if the window is not in manual handling
		if (!windowManual) {
			room.setWindowStatus(desiredWS);
		}
	}
	
	/**
	 * Apply the strategy when the room is cooler than the requested temperature.
	 * <p>
	 * This method shall set the heater value, while it shall not set the window position, which shall be returned instead.
	 * @return the desired window position for this strategy.
	 */
	protected abstract WindowState roomIsTooCool();
	
	/**
	 * Apply the strategy when the room at the requested temperature (with one degree tolerance).
	 * <p>
	 * This method shall set the heater value, while it shall not set the window position, which shall be returned instead.
	 * @return the desired window position for this strategy.
	 */
	protected abstract WindowState roomIsOK();
	
	/**
	 * Apply the strategy when the room warmer than the requested temperature.
	 * <p>
	 * This method shall set the heater value, while it shall not set the window position, which shall be returned instead.
	 * @return the desired window position for this strategy.
	 */
	protected abstract WindowState roomIsTooWarm();
	
	/**
	 * Gets the temperature that must be followed by this strategy.
	 * @return the temperature that must be followed by this strategy.
	 */
	protected abstract double getTemperatureToFollow();
}
